package cn.stylefeng.roses.kernel.manage.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.roses.kernel.manage.entity.ApiClient;
import cn.stylefeng.roses.kernel.manage.entity.ApiClientAuth;
import cn.stylefeng.roses.kernel.manage.entity.ApiEndpoint;
import cn.stylefeng.roses.kernel.manage.enums.ApiClientAuthExceptionEnum;
import cn.stylefeng.roses.kernel.manage.enums.ApiClientExceptionEnum;
import cn.stylefeng.roses.kernel.manage.enums.ApiEndpointExceptionEnum;
import cn.stylefeng.roses.kernel.manage.enums.BindTypeEnum;
import cn.stylefeng.roses.kernel.manage.mapper.ApiClientAuthMapper;
import cn.stylefeng.roses.kernel.manage.pojo.request.ApiClientAuthRequest;
import cn.stylefeng.roses.kernel.manage.pojo.response.ApiAuthBindResult;
import cn.stylefeng.roses.kernel.manage.pojo.response.ApiEndpointCheckedFlag;
import cn.stylefeng.roses.kernel.manage.service.ApiClientAuthService;
import cn.stylefeng.roses.kernel.manage.service.ApiClientService;
import cn.stylefeng.roses.kernel.manage.service.ApiEndpointService;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * API客户端和资源绑定关系业务实现层
 *
 * @author fengshuonan
 * @since 2023/10/23 22:57
 */
@Service
public class ApiClientAuthServiceImpl extends ServiceImpl<ApiClientAuthMapper, ApiClientAuth> implements ApiClientAuthService {

    @Resource
    private ApiEndpointService apiEndpointService;

    @Resource
    private ApiClientService apiClientService;

    @Override
    public ApiAuthBindResult getBindResult(ApiClientAuthRequest apiClientAuthRequest) {

        ApiAuthBindResult apiAuthBindResult = new ApiAuthBindResult();
        apiAuthBindResult.setTotalAuthCheckedFlag(true);

        // 查询所有的API接口信息
        List<ApiEndpoint> totalEndpoint = this.apiEndpointService.getTotalEndpoint();

        // 初始化所有接口信息
        List<ApiEndpointCheckedFlag> totalCheckFLagList = BeanUtil.copyToList(totalEndpoint, ApiEndpointCheckedFlag.class);

        // 获取客户端关联的所关联的资源信息
        LambdaQueryWrapper<ApiClientAuth> apiClientAuthLambdaQueryWrapper = new LambdaQueryWrapper<>();
        apiClientAuthLambdaQueryWrapper.eq(ApiClientAuth::getApiClientId, apiClientAuthRequest.getApiClientId());
        apiClientAuthLambdaQueryWrapper.select(ApiClientAuth::getResourceCode);
        List<ApiClientAuth> selectBindList = this.list(apiClientAuthLambdaQueryWrapper);

        if (ObjectUtil.isNotEmpty(selectBindList)) {
            for (ApiEndpointCheckedFlag checkFlag : totalCheckFLagList) {
                for (ApiClientAuth apiClientAuth : selectBindList) {
                    if (checkFlag.getResourceCode().equals(apiClientAuth.getResourceCode())) {
                        checkFlag.setApiCheckedFlag(true);
                    }
                }
            }
        }

        // 如果有资源没选中则设置全选状态为未全选
        for (ApiEndpointCheckedFlag totalFlag : totalCheckFLagList) {
            if (!totalFlag.getApiCheckedFlag()) {
                apiAuthBindResult.setTotalAuthCheckedFlag(false);
                break;
            }
        }

        apiAuthBindResult.setApiEndpointCheckedFlagList(totalCheckFLagList);

        return apiAuthBindResult;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bind(ApiClientAuthRequest apiClientAuthRequest) {

        // 检测客户端id是否存在
        ApiClient apiClient = apiClientService.getById(apiClientAuthRequest.getApiClientId());
        if (apiClient == null) {
            throw new ServiceException(ApiClientExceptionEnum.API_CLIENT_NOT_EXISTED);
        }

        // 如果是绑定单个资源，需要资源编码不为空
        if (BindTypeEnum.SINGLE.getCode().equals(apiClientAuthRequest.getSelectType())) {
            if (ObjectUtil.isEmpty(apiClientAuthRequest.getResourceCode())) {
                throw new ServiceException(ApiClientAuthExceptionEnum.RES_CODE_NOT_NULL);
            }
        }

        // 如果绑定所有资源
        if (BindTypeEnum.TOTAL.getCode().equals(apiClientAuthRequest.getSelectType())) {

            // 清除这个客户端绑定的所有资源
            LambdaUpdateWrapper<ApiClientAuth> apiClientAuthLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            apiClientAuthLambdaUpdateWrapper.eq(ApiClientAuth::getApiClientId, apiClientAuthRequest.getApiClientId());
            this.remove(apiClientAuthLambdaUpdateWrapper);

            if (apiClientAuthRequest.getCheckedFlag()) {
                // 查询所有的API接口信息
                List<String> totalEndpointCodeList = this.apiEndpointService.getTotalEndpointCodeList();
                // 绑定客户端对这些资源的所有权限
                ArrayList<ApiClientAuth> apiClientAuths = new ArrayList<>();
                for (String resourceCode : totalEndpointCodeList) {
                    ApiClientAuth apiClientAuth = new ApiClientAuth();
                    apiClientAuth.setApiClientId(apiClientAuthRequest.getApiClientId());
                    apiClientAuth.setResourceCode(resourceCode);
                    apiClientAuths.add(apiClientAuth);
                }
                if (ObjectUtil.isNotEmpty(apiClientAuths)) {
                    this.saveBatch(apiClientAuths);
                }
            }
        }

        // 如果是绑定的单个资源
        else if (BindTypeEnum.SINGLE.getCode().equals(apiClientAuthRequest.getSelectType())) {

            // 检测这个资源是否在库中存在
            LambdaQueryWrapper<ApiEndpoint> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ApiEndpoint::getResourceCode, apiClientAuthRequest.getResourceCode());
            long count = apiEndpointService.count(queryWrapper);
            if (count == 0) {
                throw new ServiceException(ApiEndpointExceptionEnum.API_ENDPOINT_NOT_EXISTED);
            }

            // 先清空apiClient对这个资源的权限
            LambdaUpdateWrapper<ApiClientAuth> apiClientAuthLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            apiClientAuthLambdaUpdateWrapper.eq(ApiClientAuth::getApiClientId, apiClientAuthRequest.getApiClientId());
            apiClientAuthLambdaUpdateWrapper.eq(ApiClientAuth::getResourceCode, apiClientAuthRequest.getResourceCode());
            this.remove(apiClientAuthLambdaUpdateWrapper);

            // 如果选中了这个资源，则绑定
            if (apiClientAuthRequest.getCheckedFlag()) {
                ApiClientAuth apiClientAuth = new ApiClientAuth();
                apiClientAuth.setApiClientId(apiClientAuthRequest.getApiClientId());
                apiClientAuth.setResourceCode(apiClientAuthRequest.getResourceCode());
                this.save(apiClientAuth);
            }
        }
    }

    @Override
    public boolean validateClientAuth(Long clientId, String resCode) {
        LambdaUpdateWrapper<ApiClientAuth> apiClientAuthLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        apiClientAuthLambdaUpdateWrapper.eq(ApiClientAuth::getApiClientId, clientId);
        apiClientAuthLambdaUpdateWrapper.eq(ApiClientAuth::getResourceCode, resCode);
        long count = this.count(apiClientAuthLambdaUpdateWrapper);
        return count > 0;
    }

}
